﻿using IdentityServer4.AccessTokenValidation;
using MediatR;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using Simple.Admin.EntityFrameworkCore.EntityFrameworkCore;
using Simple.Common.Core.Config;
using Simple.Common.Core.Hosting;
using Simple.Common.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;

namespace Simple.Admin.WebApi
{
    public static class ServiceCollectionExtensions
    {
        public static void MyConfigureServices(this IServiceCollection services)
        {
            var assemblies = new List<Assembly>();
            ////注入db,泛型仓储
            services.AddEntityFrameworkCoreServices<AdminDbContext>();
            ///SignalR
            services.AddSignalR();
            //注入泛型仓储
            //assemblies = AssemblyFinder.Find("*Repository").ToList();
            //List<Type> repositoryTypes = new List<Type>();
            //foreach (var assembly in assemblies)
            //{
            //    var repositories = assembly.GetTypes().Where(x => x.Name.EndsWith("Repository")).ToList();
            //    repositoryTypes.AddRange(repositories);
            //}
            //foreach (var repository in repositoryTypes.Where(x => !x.IsInterface))
            //{
            //    var iRepository = repositoryTypes.FirstOrDefault(x => x.Name == $"I{repository.Name}");
            //    if (iRepository != null)
            //    {
            //        services.AddScoped(iRepository, repository);
            //    }
            //}
            assemblies = AssemblyFinder.Find("*Application").ToList();
            //注入动态拦截器
            var interceptors = assemblies.SelectMany(x => x.GetTypes().Where(y => y.Name.EndsWith("Interceptor"))).ToList();
            interceptors.ForEach(x =>
            {
                services.AddScoped(x);
            });
            //注入services，query
            var queryServices = assemblies.SelectMany(x => x.GetTypes().Where(y => y.Name.EndsWith("Query") || y.Name.EndsWith("Service"))).ToList();
            queryServices.ForEach(x =>
            {
                services.AddScoped(x);
            });
            //注入MediatR
            services.AddMediatR(typeof(Program).Assembly);
            //services.AddMediatR(System.Reflection.Assembly.GetExecutingAssembly());
            //添加跨域
            services.AddCors(options => options.AddPolicy("any", builder => builder.AllowAnyMethod().AllowAnyHeader()
            .AllowAnyOrigin()));
            //添加全局过滤器

            //添加认证中心
            services.AddMvcCore(options =>
            {
                options.Filters.Add(new AuthorizeFilter());
            }).AddAuthorization();

            services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
                  .AddIdentityServerAuthentication(options =>
                  {
                      options.Authority = ConfigurationHelper.ServerOptions.OAuth.Authority;
                      options.RequireHttpsMetadata = ConfigurationHelper.ServerOptions.OAuth.RequireHttpsMetadata;
                      options.IntrospectionDiscoveryPolicy = new IdentityModel.Client.DiscoveryPolicy() { ValidateIssuerName = false };
                      options.ApiSecret = ConfigurationHelper.ServerOptions.OAuth.ApiSecret;
                      options.ApiName = ConfigurationHelper.ServerOptions.OAuth.ApiName;
                  });
            //添加swagger
            services.AddSwaggerGen(c =>
            {
                c.AddSecurityDefinition("Bearer", new Microsoft.OpenApi.Models.OpenApiSecurityScheme
                {
                    Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
                    Name = "Authorization",
                    //OpenIdConnectUrl = new Uri(AppConfig.ServerOptions.OAuth.Authority),
                    In = ParameterLocation.Header,
                    Type = Microsoft.OpenApi.Models.SecuritySchemeType.ApiKey
                });
                c.AddSecurityRequirement(new OpenApiSecurityRequirement {
                    {
                         new OpenApiSecurityScheme
                        {
                            Reference = new OpenApiReference
                            {
                                Type = ReferenceType.SecurityScheme,
                                Id = "Bearer"
                            }
                        },
                        new string[] { }
                    }
                });
                typeof(EnumApiVersion).GetEnumNames().ToList().ForEach(version =>
                {
                    c.SwaggerDoc(version,
                                 new OpenApiInfo
                                 {
                                     Title = ConfigurationHelper.ServerOptions.Swagger.Title,
                                     Version = version
                                 });
                });
                var basepath = System.AppContext.BaseDirectory;
                if (ConfigurationHelper.ServerOptions.Swagger.XmlFiles!=null && ConfigurationHelper.ServerOptions.Swagger.XmlFiles.Any())
                {
                    foreach (var item in ConfigurationHelper.ServerOptions.Swagger.XmlFiles)
                    {
                        var xmlpath = Path.Combine(basepath, item);
                        c.IncludeXmlComments(xmlpath);
                    }
                }

            });
        }
    }
    public enum EnumApiVersion
    {
        /// <summary>
        /// V1版本
        /// </summary>
        v1 = 1,
        /// <summary>
        /// V2版本
        /// </summary>
        v2 = 2,
        /// <summary>
        /// V3版本
        /// </summary>
        v3 = 3,
    }
}
